﻿
namespace EasyNet.Solr.Impl
{
    using System.Linq;
    using System.Xml.Linq;

    using Commons;

    /// <summary>
    /// xml格式返回数据查询结果解析器
    /// </summary>
    /// <typeparam name="T">查询结果类型</typeparam>
    public class XmlQueryResultsParser<T> : ISolrResponseParser<string, QueryResults<T>>
    {
        /// <summary>
        /// 对象反序列化器
        /// </summary>
        private readonly IObjectDeserializer<T> objectDeserialize;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="objectDeserialize">对象反序列化器</param>
        public XmlQueryResultsParser(IObjectDeserializer<T> objectDeserialize)
        {
            this.objectDeserialize = objectDeserialize;
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="result">xml格式字符串结果</param>
        /// <returns>查询结果</returns>
        public QueryResults<T> Parse(string result)
        {
            if (string.IsNullOrEmpty(result))
            {
                return null;
            }

            var queryResults = new QueryResults<T>();
            var xmlDoc = XDocument.Parse(result);

            var response = (from e in xmlDoc.Root.Elements("result")
                            where e.Attribute("name").Value == "response"
                            select e).Single();

            if (response == null)
            {
                return null;
            }

            var solrDocumentList = new SolrDocumentList()
            {
                NumFound = long.Parse(response.Attribute("numFound").Value),
                Start = long.Parse(response.Attribute("start").Value),
            };

            var maxScore = response.Attribute("maxScore");

            if (maxScore != null)
            {
                solrDocumentList.MaxScore = float.Parse(maxScore.Value);
            }

            queryResults.NumFound = solrDocumentList.NumFound;
            queryResults.MaxScore = solrDocumentList.MaxScore;

            var docs = response.Elements("doc");

            if (docs != null)
            {
                foreach (XElement ele in docs)
                {
                    var doc = new SolrDocument();

                    var items = ele.Elements();

                    foreach (var item in items)
                    {
                        var type = item.Name.LocalName;
                        var name = item.Attribute("name").Value;
                        var value = item.Value;

                        if (type != "arr")
                        {
                            doc.Add(name, value);
                        }
                        else
                        {
                            doc.Add(name, (from e in item.Elements() select e.Value).ToList<string>());
                        }
                    }

                    solrDocumentList.Add(doc);
                }

                var objs = objectDeserialize.Deserialize(solrDocumentList);

                foreach (T obj in objs)
                {
                    queryResults.Add(obj);
                }
            }

            return queryResults;
        }
    }
}
